﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//Nuget引用BouncyCastle
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.Utilities.Collections;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Crypto.Encodings;

namespace DotNet.Helper
{
    /// <summary>
    /// RSA帮助类
    /// </summary>
    public class RsaHelper
    {
        /// <summary>
        /// RSA秘钥
        /// </summary>
        private RsaKey _rsaKey;
        /// <summary>
        /// 公钥参数
        /// </summary>
        private AsymmetricKeyParameter _publicKeyParam;
        /// <summary>
        /// 私钥参数
        /// </summary>
        private AsymmetricKeyParameter _privateKeyParam;

        /// <summary>
        /// 产生RSA秘钥
        /// </summary>
        /// <returns>返回RSA的秘钥</returns>
        public RsaKey CreateRsaKey()
        {
            //RSA密钥对的构造器  
            RsaKeyPairGenerator keyGenerator = new RsaKeyPairGenerator();
            //RSA密钥构造器的参数  
            RsaKeyGenerationParameters param = new RsaKeyGenerationParameters(
                BigInteger.ValueOf(3),
                new SecureRandom(),
                1024,   //密钥长度  
                25);
            //用参数初始化密钥构造器  
            keyGenerator.Init(param);
            //产生密钥对  
            AsymmetricCipherKeyPair keyPair = keyGenerator.GenerateKeyPair();
            //获取公钥和密钥  
            _publicKeyParam = keyPair.Public;
            _privateKeyParam = keyPair.Private;

            SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(_publicKeyParam);
            PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(_privateKeyParam);

            Asn1Object asn1ObjectPublic = subjectPublicKeyInfo.ToAsn1Object();
            byte[] publicInfoByte = asn1ObjectPublic.GetEncoded("UTF-8");
            Asn1Object asn1ObjectPrivate = privateKeyInfo.ToAsn1Object();
            byte[] privateInfoByte = asn1ObjectPrivate.GetEncoded("UTF-8");

            _rsaKey = new RsaKey()
            {
                PublicKey = Convert.ToBase64String(publicInfoByte),
                PrivateKey = Convert.ToBase64String(privateInfoByte)
            };

            return _rsaKey;
        }
        /// <summary>
        /// 设置Rsa秘钥
        /// </summary>
        /// <param name="publicKey">公钥字符串</param>
        /// <param name="privateKey">私钥字符串</param>
        public void SetRsaKey(string publicKey, string privateKey)
        {
            if(_rsaKey == null)
                _rsaKey = new RsaKey();
            _rsaKey.PublicKey = publicKey;
            _rsaKey.PrivateKey = privateKey;

            if (!string.IsNullOrEmpty(publicKey))
                _publicKeyParam = GetPublicKeyParameter(publicKey);

            if (!string.IsNullOrEmpty(privateKey))
                _privateKeyParam = GetPrivateKeyParameter(privateKey);
        }
        /// <summary>
        /// 通过私钥加密
        /// </summary>
        /// <param name="input">需要加密的字符串</param>
        /// <returns>加密后的字符串</returns>
        public string EncryptByPrivateKey(string input)
        {
            //非对称加密算法，加解密用  
            IAsymmetricBlockCipher engine = new Pkcs1Encoding(new RsaEngine());
            //加密  
            try
            {
                engine.Init(true, _privateKeyParam);
                byte[] byteData = Encoding.UTF8.GetBytes(input);
                var resultData = engine.ProcessBlock(byteData, 0, byteData.Length);
                return Convert.ToBase64String(resultData);
            }
            catch (Exception)
            {
                throw;
            }
        }
        /// <summary>
        /// 通过公钥加密
        /// </summary>
        /// <param name="input">需要加密的字符串</param>
        /// <returns>加密后的字符串</returns>
        public string EncryptByPublicKey(string input)
        {
            //非对称加密算法，加解密用  
            IAsymmetricBlockCipher engine = new Pkcs1Encoding(new RsaEngine());
            //加密  
            try
            {
                engine.Init(true, _publicKeyParam);
                byte[] byteData = Encoding.UTF8.GetBytes(input);
                var resultData = engine.ProcessBlock(byteData, 0, byteData.Length);
                return Convert.ToBase64String(resultData);
            }
            catch (Exception)
            {
                throw;
            }
        }
        /// <summary>
        /// 通过公钥解密
        /// </summary>
        /// <param name="input">需要解密的字符串</param>
        /// <returns>解密后的字符串</returns>
        public string DecryptByPublicKey(string input)
        {
            //非对称加密算法，加解密用  
            IAsymmetricBlockCipher engine = new Pkcs1Encoding(new RsaEngine());
            //解密  
            try
            {
                engine.Init(false, _publicKeyParam);
                byte[] byteData = Convert.FromBase64String(input);
                var resultData = engine.ProcessBlock(byteData, 0, byteData.Length);
                return Encoding.UTF8.GetString(resultData);
            }
            catch (Exception)
            {
                throw;
            }
        }
        /// <summary>
        /// 通过私钥解密
        /// </summary>
        /// <param name="input">需要解密的字符串</param>
        /// <returns>解密后的字符串</returns>
        public string DecryptByPrivateKey(string input)
        {
            //非对称加密算法，加解密用  
            IAsymmetricBlockCipher engine = new Pkcs1Encoding(new RsaEngine());
            //解密  
            try
            {
                engine.Init(false, _privateKeyParam);
                byte[] byteData = Convert.FromBase64String(input);
                var resultData = engine.ProcessBlock(byteData, 0, byteData.Length);
                return Encoding.UTF8.GetString(resultData);
            }
            catch (Exception)
            {
                throw;
            }
        }


        #region 私有方法
        /// <summary>
        /// 根据公钥字符串获取公钥参数
        /// </summary>
        /// <param name="publicKeyStr">公钥字符串</param>
        /// <returns>公钥参数</returns>
        private AsymmetricKeyParameter GetPublicKeyParameter(string publicKeyStr)
        {
            publicKeyStr = publicKeyStr.Replace("\r", "").Replace("\n", "").Replace(" ", "");
            byte[] publicInfoByte = Convert.FromBase64String(publicKeyStr);
            AsymmetricKeyParameter pubKey = PublicKeyFactory.CreateKey(publicInfoByte);
            return pubKey;
        }
        /// <summary>
        /// 根据私钥字符串获取私钥参数
        /// </summary>
        /// <param name="privateKeyStr">私钥字符串</param>
        /// <returns>私钥参数</returns>
        private AsymmetricKeyParameter GetPrivateKeyParameter(string privateKeyStr)
        {
            privateKeyStr = privateKeyStr.Replace("\r", "").Replace("\n", "").Replace(" ", "");
            byte[] privateInfoByte = Convert.FromBase64String(privateKeyStr);
            AsymmetricKeyParameter priKey = PrivateKeyFactory.CreateKey(privateInfoByte);
            return priKey;
        }
        #endregion

    }

    /// <summary>
    /// Rsa秘钥
    /// </summary>
    public class RsaKey
    {
        /// <summary>
        /// 公钥字符串
        /// </summary>
        public string PublicKey { get; set; }
        /// <summary>
        /// 私钥字符串
        /// </summary>
        public string PrivateKey { get; set; }
    }
}
